package com.bluexmicro.bluetooth.peripheral.handler

import android.annotation.SuppressLint
import android.bluetooth.BluetoothGatt
import android.os.Build
import com.bluexmicro.bluetooth.model.GattStatus
import com.bluexmicro.bluetooth.model.Phy
import kotlinx.coroutines.CancellableContinuation
import kotlinx.coroutines.suspendCancellableCoroutine
import kotlin.coroutines.resume


typealias PhyCallback = (gatt: BluetoothGatt, txPhy: Int, rxPhy: Int, status: Int) -> Unit


class PhyHandler {

    private var readCallback: PhyCallback? = null
    private var updateCallback: PhyCallback? = null
    private var readCancellableContinuation: CancellableContinuation<Result<Phy>>? = null
    private var setCancellableContinuation: CancellableContinuation<Result<Phy>>? = null

    fun onPhyRead(gatt: BluetoothGatt, txPhy: Int, rxPhy: Int, status: Int) {
        readCallback?.invoke(gatt, txPhy, rxPhy, status)
    }

    fun onPhyUpdate(gatt: BluetoothGatt, txPhy: Int, rxPhy: Int, status: Int) {
        updateCallback?.invoke(gatt, txPhy, rxPhy, status)
    }

    private fun setReadCallback(cb: PhyCallback) {
        this.readCallback = cb
    }

    private fun setUpdateCallback(cb: PhyCallback) {
        this.updateCallback = cb
    }

    fun isReadActive(): Boolean {
        return readCancellableContinuation?.isActive == true
    }

    fun isSetActive(): Boolean {
        return setCancellableContinuation?.isActive == true
    }

    @SuppressLint("MissingPermission")//断言是获取了权限的
    suspend fun executeRead(gatt: BluetoothGatt) = suspendCancellableCoroutine<Result<Phy>> {
        readCancellableContinuation = it
        setReadCallback { _, txPhy, rxPhy, status ->
            this.readCallback = null
            if (it.isActive) {
                if (status == BluetoothGatt.GATT_SUCCESS) {
                    it.resume(Result.success(Phy(txPhy, rxPhy)))
                } else {
                    val reason = GattStatus.fromValue(status).name
                    it.resume(Result.failure(Throwable("Read Phy Failed, gatt errorCode:$status, reason: $reason")))
                }
            }
        }
        if (it.isActive) {
            if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
                gatt.readPhy()
            } else {
                it.resume(Result.failure(Throwable("The mobile software version does not support this function, at least greater than Android O")))
            }
        }

        it.invokeOnCancellation {
            this.readCallback = null
        }
    }

    @SuppressLint("MissingPermission")//断言是获取了权限的
    suspend fun executeSet(gatt: BluetoothGatt, txPhy: Int, rxPhy: Int, options: Int) =
        suspendCancellableCoroutine<Result<Phy>> {
            setCancellableContinuation = it
            setUpdateCallback { _, txPhy, rxPhy, status ->
                this.updateCallback = null
                if (it.isActive) {
                    if (status == BluetoothGatt.GATT_SUCCESS) {
                        it.resume(Result.success(Phy(txPhy, rxPhy)))
                    } else {
                        val reason = GattStatus.fromValue(status).name
                        it.resume(Result.failure(IllegalStateException("set Phy Failed, gatt errorCode:$status, reason: $reason")))
                    }
                }
            }
            if (it.isActive) {
                if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
                    gatt.setPreferredPhy(txPhy, rxPhy, options)
                } else {
                    this.updateCallback = null
                    it.resume(Result.failure(Throwable("The mobile software version does not support this function, at least greater than Android O")))
                }
            }

            it.invokeOnCancellation {
                this.updateCallback = null
            }
        }
}